
import { _decorator, Component, Node, TiledMap, Sprite ,resources ,SpriteFrame ,Button ,EventHandler ,log
    ,TiledObjectGroup ,UITransform ,Vec3 ,TiledLayer ,Layout} from 'cc';
const { ccclass, property } = _decorator;

/**
 * Predefined variables
 * Name = RunGame
 * DateTime = Tue Nov 02 2021 14:52:12 GMT+0800 (中国标准时间)
 * Author = yly1234560
 * FileBasename = RunGame.ts
 * FileBasenameNoExtension = RunGame
 * URL = db://assets/scripts/RunGame.ts
 * ManualUrl = https://docs.cocos.com/creator/3.3/manual/zh/
 *
 */
 
@ccclass('RunGame')
export class RunGame extends Component {
    // [1]
    // dummy = '';

    // [2]
    // @property
    // serializableDummy = 0;

    @property({type:TiledMap})
    private tiledMap;
    @property({type:Layout})
    private alert;

    // 动物脚印 后期优化可使用 不同的动物显示不同的脚印
    private footPrint:Node[] = [null,null,null,null];

    // 陷阱
    private mapTrap = new Map();
    // 河流
    private mapRiver = new Map();
    // 兽穴
    private mapBen = new Map();
    // 棋子
    private mapPieces = new Map();

    // 回合 fasle蓝方  true红方 默认蓝方先走
    private round:boolean = false;

    // 脚印
    private sffp: SpriteFrame;

    // 点击棋子的名字
    private clickName:string = "";


    start () {
        // [3]


        // 初始化 方法 添加 脚印精灵
        this.initFootPrint();
        // 初始化所有棋子
        this.initPieces();
        // 初始化兽穴、陷阱、河道
        this.initBlock();

    }

    // update (deltaTime: number) {
    //     // [4]
    // }

    /*** foot print start ****/
    private initFootPrint(){
        this.footPrint[0]=this.createFootPrint("left");
        this.footPrint[1]=this.createFootPrint("up");
        this.footPrint[2]=this.createFootPrint("down");
        this.footPrint[3]=this.createFootPrint("right");
    }

    private createFootPrint(type:string): Node {
        let footprint_node = new Node();
        footprint_node.name = type;
        footprint_node.parent = this.node;
        // 爪印
        let footprint = footprint_node.addComponent(Sprite);
        resources.load("pieces/6/spriteFrame", SpriteFrame, (err, spriteFrame) => {
            footprint.spriteFrame =  spriteFrame;
        });
        // 设置层级
        footprint_node.layer = 33554432;
        // 设置锚点
        let ui = footprint_node.getComponent(UITransform);
        ui.setAnchorPoint(0,0);


        // 添加事件
        const clickEventHandler = new EventHandler();
        clickEventHandler.target = this.node; // 这个 node 节点是你的事件处理代码组件所属的节点
        clickEventHandler.component = 'RunGame';// 这个是脚本类名
        clickEventHandler.handler = 'onClickMove';
        clickEventHandler.customEventData = '';

        const button= footprint_node.addComponent(Button);
        button.clickEvents.push(clickEventHandler);

        return footprint_node;
    }

    // 隐藏或显示脚印
    private isShowFootPrint(active:boolean){
        for (let i = 0; i < this.footPrint.length; i++) {
            this.footPrint[i].active = active;
            if(active){
                // 超出边界的不显示
                if(this.footPrint[i].position.x<0 || this.footPrint[i].position.x>888
                    || this.footPrint[i].position.y<148 || this.footPrint[i].position.y>1332){
                    this.footPrint[i].active = false;
                }

                // 自己阵营的兽血不显示
                if(this.mapBen.has(this.getObstaclesKey(this.footPrint[i].position.x,this.footPrint[i].position.y))){
                    // 红色 不能进入自家兽穴
                    if(this.clickName.indexOf("r_") != -1 && this.footPrint[i].position.y>666){
                        this.footPrint[i].active = false;
                    }
                    // 蓝色 不能计入自家兽穴
                    if(this.clickName.indexOf("b_") != -1 && this.footPrint[i].position.y<666){
                        this.footPrint[i].active = false;
                    }
                }

                // 如果是河道 老鼠可以行走 老虎狮子可以通过 其他动物不能
                if(this.mapRiver.has(this.getObstaclesKey(this.footPrint[i].position.x,this.footPrint[i].position.y))){
                    // 不是老鼠 行走路径不显示
                    if(this.clickName.indexOf("_mouse") == -1){
                        this.footPrint[i].active = false;
                    }
                    // 老虎和狮子可跳过河道
                    if(this.clickName.indexOf("_lion") != -1 || this.clickName.indexOf("_tiger") != -1 ){

                        let clickNode = this.getPieceNodeByName(this.clickName);
                        // 老虎狮子跳过河水 并且路径上没有老鼠时
                        if(this.footPrint[i].name == "left" && !this.checkRiverHasMouse(this.footPrint[i])){
                            this.footPrint[i].setPosition(clickNode.position.x - 148*3,this.footPrint[i].position.y);
                            this.footPrint[i].active = true;
                        }
                        log("this.footPrint[i]:{}",i);
                        log("this.footPrint[i]:{}",!this.checkRiverHasMouse(this.footPrint[i]));
                        if(this.footPrint[i].name == "right" && !this.checkRiverHasMouse(this.footPrint[i])){
                            log("i'm in hegou");
                            this.footPrint[i].setPosition(clickNode.position.x + 148*3,this.footPrint[i].position.y);
                            this.footPrint[i].active = true;
                        }
                        if(this.footPrint[i].name == "down" && !this.checkRiverHasMouse(this.footPrint[i])){
                            this.footPrint[i].setPosition(clickNode.position.x,this.footPrint[i].position.y - 148*3);
                            this.footPrint[i].active = true
                        }
                        if(this.footPrint[i].name == "up" && !this.checkRiverHasMouse(this.footPrint[i])){
                            this.footPrint[i].setPosition(clickNode.position.x,this.footPrint[i].position.y+ 148*3);
                            this.footPrint[i].active = true;
                        }

                    }

                }


                // 已有棋子不显示
                if(this.getPieceNodeByPosition(this.footPrint[i].position)){
                    this.footPrint[i].active = false;
                }
            }
        }
    }

    // 检查河流中是否有老鼠
    private checkRiverHasMouse(node:Node):Node{
        for (let i = 1; i <= 2; i++) {
            if(node.name == "left"){
                return this.getPieceNodeByPosition(new Vec3(node.position.x-148*i,node.position.y));
            }
            if(node.name == "right"){
                return this.getPieceNodeByPosition(new Vec3(node.position.x+148*i,node.position.y));
            }
            if(node.name == "up"){
                return this.getPieceNodeByPosition(new Vec3(node.position.x,node.position.y+148*i));
            }
            if(node.name == "wod"){
                return this.getPieceNodeByPosition(new Vec3(node.position.x,node.position.y-148*i));
            }
        }
        return null;
    }
    private checkRiverHasMouse2(node:Node,dir:string):Node{
        for (let i = 1; i <= 2; i++) {
            if(node.name == dir){
                return this.getPieceNodeByPosition(new Vec3(node.position.x-148*i,node.position.y));
            }
            if(node.name == dir){
                return this.getPieceNodeByPosition(new Vec3(node.position.x+148*i,node.position.y));
            }
            if(node.name == dir){
                return this.getPieceNodeByPosition(new Vec3(node.position.x,node.position.y+148*i));
            }
            if(node.name == dir){
                return this.getPieceNodeByPosition(new Vec3(node.position.x,node.position.y-148*i));
            }
        }
        return null;
    }
    /*** foot print end ****/



    /*** pieces start ****/
    private initPieces() {
        let pieces = this.tiledMap.getObjectGroup('pieces');
        let objects = pieces.getObjects();

        let node_pieces = this.node.getChildByName("lay_pieces");


        const clickEventHandler = new EventHandler();
        clickEventHandler.target = this.node; // 这个 node 节点是你的事件处理代码组件所属的节点
        clickEventHandler.component = 'RunGame';// 这个是脚本类名
        clickEventHandler.handler = 'piecesOnClick';
        clickEventHandler.customEventData = '';

        // 绑定点击事件
        for(let i = 0;i<objects.length;i++) {
            let object = objects[i];

            // 设置棋子
            this.mapPieces.set(object.name,object);

            let node = node_pieces.getChildByName(object.name);

            // 获取到精灵
            let sprite = node.getComponent(Sprite);
            resources.load("pieces/"+object.name+"/spriteFrame", SpriteFrame, (err, spriteFrame) => {
                sprite.spriteFrame = spriteFrame;
            });


            const button= node.addComponent(Button);
            button.clickEvents.push(clickEventHandler);
        }

    }

    // 点击棋子时
    piecesOnClick(event, customEventData){
        let node = event.target;
        // let button = node.getComponent(Sprite);
        // console.log("node=", node.name, " event=", event.type, " data=", customEventData);
        // console.log("node.x=", node.position.x ," node.y", node.position.y, " event=", event.type, " data=", customEventData);

        // if(this.clickName.length>0){
        //     // true 是红方行动， false 是否蓝方行动
        //     if(this.round && "b_"==node.name.substr(0,2)){
        //         return false;
        //     }
        // }






        // 排除掉 未选择时 和 非同阵营
        if(this.clickName!="" && this.clickName.substr(0,2) != node.name.substr(0,2)){
            // 校验是否在旁边 并且 是否可以吃掉
            if(this.isNear(node) && this.isAction(node)){
                this.isShowFootPrint(false);

                // 移动棋子
                this.moveClickPieces(node.position.x,node.position.y);

                // 被吃掉 销毁
                node.destroy();
                return;
            }
        }



        // this.round 是红方行动时 当前点击的棋子不能是蓝方
        if (this.round) {
            if("b_" == node.name.substr(0, 2)){
                return;
            }
        }else{
            if("r_" == node.name.substr(0, 2)){
                return;
            }
        }




        // 点击后记录当前棋子
        this.clickName = node.name;
        // 显示可以行走的路径
        this.showFoot(node);
    }

    // 该行动的棋子是否 可行动
    private isNear(node:Node):boolean{
        // 获取点击的按钮
        let cn = this.getPieceNodeByName(this.clickName);


        // 如果是老鼠不能吃岸上的大象  岸上的动物也不能吃 水里的老鼠

        // 当前行动者不是老鼠 但是目标在水里    不可行动
        if(this.clickName.indexOf("_mouse") == -1 && this.mapRiver.has(this.getObstaclesKey(node.position.x,node.position.y))){
            return false;
        }

        // 当前行动者是老鼠 并且 在水里 ，目标在陆地    不可行动
        if(this.clickName.indexOf("_mouse") != -1 && this.mapRiver.has(this.getObstaclesKey(cn.position.x,cn.position.y))
            && !this.mapRiver.has(this.getObstaclesKey(node.position.x,node.position.y))){
            return false;
        }


        // 老虎和狮子可跳过河道 需要多判断河对岸是否有棋子
        if(this.clickName.indexOf("_lion") != -1 || this.clickName.indexOf("_tiger") != -1 ){
            // 左边是否是河道 并且 目标在对岸 并且河道内没有老鼠
            if(this.mapRiver.has(this.getObstaclesKey(cn.position.x-148,cn.position.y))
                && this.mapRiver.has(this.getObstaclesKey(node.position.x+148,node.position.y))
                && cn.position.y == node.position.y
                && !this.checkRiverHasMouse2(cn,"left")){
                return this.getObstaclesKey(cn.position.x-148*3,cn.position.y) == this.getObstaclesKey(node.position.x,node.position.y);
            }
            if(this.mapRiver.has(this.getObstaclesKey(cn.position.x+148,cn.position.y))
                && this.mapRiver.has(this.getObstaclesKey(node.position.x-148,node.position.y))
                && cn.position.y == node.position.y
                && !this.checkRiverHasMouse2(cn,"rigth")){
                return this.getObstaclesKey(cn.position.x+148*3,cn.position.y) == this.getObstaclesKey(node.position.x,node.position.y);
            }
            if(this.mapRiver.has(this.getObstaclesKey(cn.position.x,cn.position.y-148))
                && this.mapRiver.has(this.getObstaclesKey(node.position.x,node.position.y+148))
                && cn.position.x== node.position.x
                && !this.checkRiverHasMouse2(cn,"down")){
                return this.getObstaclesKey(cn.position.x,cn.position.y-148*4) == this.getObstaclesKey(node.position.x,node.position.y);
            }
            if(this.mapRiver.has(this.getObstaclesKey(cn.position.x,cn.position.y+148))
                && this.mapRiver.has(this.getObstaclesKey(cn.position.x,cn.position.y-148))
                && cn.position.x == node.position.x
                && !this.checkRiverHasMouse2(cn,"up")){
                return this.getObstaclesKey(cn.position.x,cn.position.y+148*4) == this.getObstaclesKey(node.position.x,node.position.y);
            }
        }

        // 其他动物
        return this.getObstaclesKey(cn.position.x,cn.position.y) == this.getObstaclesKey(node.position.x+148,node.position.y)
            || this.getObstaclesKey(cn.position.x,cn.position.y) == this.getObstaclesKey(node.position.x-148,node.position.y)
            || this.getObstaclesKey(cn.position.x,cn.position.y) == this.getObstaclesKey(node.position.x,node.position.y+148)
            || this.getObstaclesKey(cn.position.x,cn.position.y) == this.getObstaclesKey(node.position.x,node.position.y-148);
    }

    // 是否可以吃掉
    private isAction(node:Node):boolean{
        // 获取点击的按钮
        let cn = this.getPieceNodeByName(this.clickName);


        let oldObj = this.mapPieces.get(this.clickName);
        let newObj = this.mapPieces.get(node.name);

        // 0是老鼠 7是大象
        if(oldObj.power == 0 && newObj.power == 7){
            return true;
        }
        // 大象不能吃老鼠
        if(oldObj.power == 7 && newObj.power == 0){
            return false;
        }

        // 目标在陷阱中
        let newKey = this.getObstaclesKey(node.position.x,node.position.y);
        if(this.mapTrap.has(newKey)){
            // 在陷阱中并且陷阱中的棋子非本阵营的 可以吃掉
            let type = node.name.substr(0,2);
            if(type=="r_")type="red";
            else type="blue";
            log(newObj);
            if(this.mapTrap.get(newKey) != type){
                return true;
            }
        }


        // 其他动物正常的顺序 0~7
        return oldObj.power >= newObj.power;

    }

    // 显示爪印
    private showFoot(node:Node){

        let x = node.position.x;
        let y = node.position.y;


        for (let i = 0; i < this.footPrint.length; i++) {
            let fp = this.footPrint[i];
            if(fp.name == "left"){
                fp.setPosition(x-148,y);
            }
            if(fp.name == "up"){
                fp.setPosition(x,y+148);
            }
            if(fp.name == "down"){
                fp.setPosition(x,y-148);
            }
            if(fp.name == "right"){
                fp.setPosition(x+148,y);
            }
        }
        this.isShowFootPrint(true);
    }

    onClickMove(event, customEventData){
        this.isShowFootPrint(false);

        let node = event.target;
        this.moveClickPieces(node.position.x,node.position.y);

        if(this.alert.node.active)this.alert.node.active = false;
        // 进入兽穴时 弹出获胜
        if(this.mapBen.has(this.getObstaclesKey(node.position.x,node.position.y))){
            this.alert.node.active = true;
        }
    }

    // 移动选中的棋子
    private moveClickPieces(x:number,y:number){
        let moveNode = this.getPieceNodeByName(this.clickName);
        moveNode.setPosition(x,y);

        // 移动棋子后回合结束 对方行动
        this.round = !this.round;
        // 行动结束后 清空选中的节点名
        this.clickName="";
    }

    /*** pieces  end ****/

    /**** chessboard start ******/
    chessboardOnClick(event, customEventData){

        let node = event.target;
        let button = node.getComponent(Sprite);
        // console.log("node=", node.name, " event=", event.type, " data=", customEventData);

        if("" != this.clickName){
            this.clickName = "";
        }

        this.isShowFootPrint(false);
    }
    /**** chessboard end******/



    /*** 公共方法 *****/
    // 根据名字获取棋子
    private getPieceNodeByName(name:string):Node{
        return  this.node.getChildByName("lay_pieces").getChildByName(name);
    }
    // 根据坐标获取棋子
    private getPieceNodeByPosition(position:Vec3):Node{
        let lp = this.node.getChildByName("lay_pieces");

        // 所有子节点
        let children_node = lp.children;


        for (let i = 0; i < children_node.length; i++) {
            let node = children_node[i];
            if(node.position.x == position.x && node.position.y == position.y){
                return node;
            }
        }
        return null;
    }

    // 获取障碍key
    private getObstaclesKey(x,y):String{
        return x+"_"+y;
    }


    /******* 陷阱、河道、兽穴 start **********/
    private initBlock(){
        // 陷阱
        let trap = this.node.getChildByName("trap").getComponent(TiledLayer);

        for (let i = 0; i < 7; i++) {
            for (let j = 0; j < 9; j++) {
                if(trap.getTileGIDAt(i, j)!=0){
                    let positionAt = trap.getPositionAt(i, j);
                    // 陷阱区分阵营
                    let camp = "blue";
                    if(positionAt.y > 666) camp = "red";
                    this.mapTrap.set(this.getObstaclesKey(positionAt.x,positionAt.y),camp);

                }
            }
        }

        // 兽穴 tiled 未指定 den
        // let childByName1 = this.tiledMap.getChildByName("lay_pieces");
        this.mapBen.set(this.getObstaclesKey(444,1332),"red");
        this.mapBen.set(this.getObstaclesKey(444,148),"blue");



        // 河道
        let river = this.node.getChildByName("block").getComponent(TiledLayer);

        for (let i = 0; i < 7; i++) {
            for (let j = 0; j < 9; j++) {
                if(river.getTileGIDAt(i, j)!=0){
                    let positionAt = river.getPositionAt(i, j);;
                    this.mapRiver.set(this.getObstaclesKey(positionAt.x,positionAt.y),"");

                }
            }
        }

    }
    /******* 陷阱、河道、兽穴 end **********/

}

/**
 * [1] Class member could be defined like this.
 * [2] Use `property` decorator if your want the member to be serializable.
 * [3] Your initialization goes here.
 * [4] Your update function goes here.
 *
 * Learn more about scripting: https://docs.cocos.com/creator/3.3/manual/zh/scripting/
 * Learn more about CCClass: https://docs.cocos.com/creator/3.3/manual/zh/scripting/ccclass.html
 * Learn more about life-cycle callbacks: https://docs.cocos.com/creator/3.3/manual/zh/scripting/life-cycle-callbacks.html
 */
